package simpleGui;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import processing.core.PApplet;
import processing.core.PGraphics;

public class PCam2DGraphics implements MouseListener, KeyListener,  MouseMotionListener {
PApplet pApplet;

public float scale = 1;
public float tX = 0;
public float tY = 0;
public float rx1,ry1,rx2,ry2;//zoomrect
float bx1,by1,bx2,by2;//bounds of the model
PGraphics g;
boolean dragMode;
int startDragX;
int startDragY;
public int screenX;
public int screenY;
public int screenWidth;
public int screenHeight;

public PCam2DGraphics(PApplet pApplet){
	this.pApplet=pApplet;
	pApplet.addMouseListener(this);
	pApplet.addKeyListener(this);
	pApplet.addMouseMotionListener(this);
	rx1=0;
	ry1=0;
	rx2=pApplet.width;
	ry2=pApplet.height;
	bx1=0;
	by1=0;
	bx2=pApplet.width;
	by2=pApplet.height;
	screenWidth=pApplet.width;
	screenHeight=pApplet.height;
}
public void setScreen(int x,int y,int w,int h){
	screenX=x;
	screenY=y;
	screenWidth=w;
	screenHeight=h;
}
public int getScreenX(float modelX){
	return (int)((modelX+tX)*scale);
}
public int getScreenY(float modelY){
	return (int)((modelY+tY)*scale);
}
public float getModelX(float screenX) {
	return (screenX - tX) / scale;
}

public float getModelY(float screenY) {
	return (screenY - tY) / scale;
}
public void useCam(PGraphics g){
	this.g=g;
	this.zoomToBounds(rx1,ry1,rx2,ry2);
	g.translate(tX,tY);
	g.scale(scale);
	
}


public void mouseEntered(MouseEvent arg0) {
	// TODO Auto-generated method stub
	
}
public void mouseExited(MouseEvent arg0) {
	// TODO Auto-generated method stub
	
}
public void mousePressed(MouseEvent arg0) {
	
	//if (pApplet.)
	if (dragMode){
		startDragX=pApplet.mouseX;
		startDragY=pApplet.mouseY;
		return;
	}
	
	float x = this.getModelX(pApplet.mouseX);
	float y = this.getModelY(pApplet.mouseY);
	float f=1;
	
	if (arg0.isAltDown()){
		f=0.5f;
	}
	else if (arg0.isControlDown()){
		f=2f;
	}
	/*else if (arg0.isShiftDown()){
		f=1f;
	}*/
	else return;
	float cW = (rx2-rx1) *f;
	float cH = (ry2-ry1) *f;
	rx1=x - cW * 0.5f;
	rx2=x + cW * 0.5f;
	ry1=y - cH * 0.5f;
	ry2=y + cH * 0.5f;
}
public void mouseReleased(MouseEvent arg0) {
	// TODO Auto-generated method stub
	
}

public void keyPressed(KeyEvent arg0) {
	// TODO Auto-generated method stub
	
	if (arg0.getKeyChar()== 'b') {
		System.out.println("zoom to bounds");
		zoomToBounds(pApplet.g);
	}
	if (arg0.getKeyChar()== ' ') {
		dragMode=true;
	}
}

public void keyReleased(KeyEvent arg0) {
	// TODO Auto-generated method stub
	if (arg0.getKeyChar()== ' ') {
		dragMode=false;
	}
}

public void keyTyped(KeyEvent arg0) {
	// TODO Auto-generated method stub
	
}
public void zoomToBounds(PGraphics g){
	rx1=bx1;
	ry1=by1;
	rx2=bx2;
	ry2=by2;
	zoomToBounds(rx1,ry1,rx2,ry2,g);
}
public void zoomToBounds(){
	rx1=bx1;
	ry1=by1;
	rx2=bx2;
	ry2=by2;
	zoomToBounds(rx1,ry1,rx2,ry2);
}
public void zoomToBounds(float x1,float y1,float x2,float y2,PGraphics g) {
	float sX = (float)((g.width ) / (x2-x1));
	float sY = (float)((g.height ) / (y2-y1));
	scale = pApplet.min(sX, sY);
	
	tX = (float)(g.width * 0.5f - (x1+x2)*0.5f * scale);
	tY = (float)(g.height * 0.5f - (y1+y2)*0.5f * scale);
	
}
public void zoomToBounds(float x1,float y1,float x2,float y2) {
	float sX = (float)((screenWidth ) / (x2-x1));
	float sY = (float)((screenHeight ) / (y2-y1));
	scale = pApplet.min(sX, sY);
	
	tX = (float)((screenWidth * 0.5f+screenX) - (x1+x2)*0.5f * scale);
	tY = (float)((screenHeight * 0.5f+screenY) - (y1+y2)*0.5f * scale);
	
}


public void setBounds(float x1,float y1,float x2,float y2) {
	bx1=x1;
	by1=y1;
	bx2=x2;
	by2=y2;
}

public void mouseClicked(MouseEvent e) {
	// TODO Auto-generated method stub
	
}

@Override
public void mouseDragged(MouseEvent arg0) {
	if (dragMode){
		float dX=(pApplet.mouseX-startDragX)/scale;
		float dY=(pApplet.mouseY-startDragY)/scale;
		rx1-=dX;
		rx2-=dX;
		ry1-=dY;
		ry2-=dY;
		startDragX=pApplet.mouseX;
		startDragY=pApplet.mouseY;
		return;
	}
}

@Override
public void mouseMoved(MouseEvent arg0) {
	// TODO Auto-generated method stub
	
}

public boolean isDragMode() {
	return dragMode;
}

public void setDragMode(boolean dragMode) {
	this.dragMode = dragMode;
}
}
